package com.huawei.admins.platform.gateway.core.component.filter.factory;

import com.huawei.admins.platform.gateway.core.component.filter.FilterDefinition;
import com.huawei.admins.platform.gateway.core.component.filter.GatewayFilterFactory;
import com.huawei.admins.platform.gateway.core.component.router.RouteDefinition;
import com.huawei.admins.platform.gateway.core.config.GatewayProperties;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public abstract class AbstractGatewayFilterFactory<T> implements GatewayFilterFactory, ApplicationEventPublisherAware {

    private ApplicationEventPublisher publisher;

    private final GatewayProperties properties;

    private final Map<String, FilterDefinition> routeConfigMap = new HashMap<>();

    private final FilterDefinition defaultFilterConfig;


    public AbstractGatewayFilterFactory(GatewayProperties properties) {
        this.properties = properties;

        String filterName = name();
        for (RouteDefinition route : properties.getRoutes()) {
            List<FilterDefinition> definitions = route.getFilters().stream()
                    .filter(x -> x.getName().equals(filterName))
                    .toList();
            if (!definitions.isEmpty()) {
                routeConfigMap.put(route.getId(), definitions.getFirst());
            }
        }
        FilterDefinition defaultRetryConfig = null;
        for (FilterDefinition defaultFilter : properties.getDefaultFilters()) {
            if (defaultFilter.getName().equals(filterName)) {
                defaultRetryConfig = defaultFilter;
            }
        }
        this.defaultFilterConfig = defaultRetryConfig;
    }

    protected T loadConfiguration(String routeId) {

        FilterDefinition filterDefinition = routeConfigMap.get(routeId);
        Map<String, String> filterArgs = new HashMap<>();
        if (filterDefinition != null) {
            filterArgs = filterDefinition.getArgs();
        }
        if (filterArgs.isEmpty()) {
            filterArgs = defaultFilterConfig.getArgs();
        }
        if (filterArgs.isEmpty()) {
            throw new IllegalArgumentException("No Configuration found for route " + routeId + " or defaultFilters");
        }
        return buildConfig(routeId, filterArgs);
    }

    protected abstract T buildConfig(String routeId, Map<String, String> filterArgs);

    protected ApplicationEventPublisher getPublisher() {
        return this.publisher;
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }

}
